package cn.lgp6.ziyou_util.excel.controller;
import cn.lgp6.ziyou_util.excel.entity.dto.ExcelMessageDTO;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Component
@ServerEndpoint("/excel/queue")
public  class ExcelWebSocketController {
    private static Logger logger=LoggerFactory.getLogger(ExcelWebSocketController.class);
    //记录队列用户
    public static Map<Session,Integer> userMap=new ConcurrentHashMap<>();
    //记录用户编号
    private static volatile AtomicInteger atomicInteger=new AtomicInteger(0);
    //记录总用户数量
    public static volatile  Map<Session,String> total=new ConcurrentHashMap<>();

    public synchronized static void sendText(Session session, ExcelMessageDTO messageDTO, String methodName) {
        synchronized (session){
            logger.info(methodName+"调用发送方法");
            try {
                session.getBasicRemote().sendText(JSON.toJSONString(messageDTO));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public synchronized void onOpen(Session session) {
        total.put(session,"0");
        logger.info("新连接{"+session.getId()+"}加入,当前总人数:"+total.size()+",队列人数:"+userMap.size());
        ExcelMessageDTO messageDTO=new ExcelMessageDTO();
        messageDTO.setType("message");
        messageDTO.setMsg("成功连接到服务器");
        try {
            session.getBasicRemote().sendText(JSON.toJSONString(messageDTO));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public static synchronized void onClose(Session session) {
        ExcelMessageDTO messageDTO=new ExcelMessageDTO();
        total.remove(session);
        if (session.isOpen()){
            messageDTO.setMsg("您与队列服务器连接已关闭");
            messageDTO.setType("error");
            sendText(session,messageDTO,"onclose");
        }
        if (userMap.get(session)!=null&&userMap.get(session)!=0){
            Integer closeNum = userMap.get(session);
            userMap.remove(session);
            for (Session session1 : userMap.keySet()) {
                if (userMap.get(session1)>closeNum){
                    messageDTO.setMsg("您上一位用户离开队列或操作完成,您前进一位,当前您前面还有"+getPreNum(session1)+"位用户");
                    messageDTO.setType("finish");
                    messageDTO.setPre(getPreNum(session1));
                    sendText(session1,messageDTO,"close");
                }
            }


        }
        logger.info("用户{"+session.getId()+"}关闭连接");
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     *            客户端发送过来的消息
     */
    @OnMessage
    public synchronized void onMessage(Session session,String message) {
        if ("join".equals(message)){
            //保存用户
            int num = atomicInteger.incrementAndGet();
            userMap.put(session,num);
            int pre=getPreNum(session);
            ExcelMessageDTO messageDTO=new ExcelMessageDTO();
            messageDTO.setMsg("您已进入队列,序号:"+num+",您之前还有:"+pre+"位用户");
            messageDTO.setNum(num);
            messageDTO.setPre(pre);
            messageDTO.setSessionId(session.getId());
            messageDTO.setType("start");
            try {
                session.getBasicRemote().sendText(JSON.toJSONString(messageDTO));
            } catch (IOException e) {
                e.printStackTrace();
            }
            logger.info("用户{"+session.getId()+"}进入队列,当前队列人数:"+userMap.size());
        }

    }

    private static int getPreNum(Session session) {
        int num=0;
        for (Session sessionEach : userMap.keySet()) {
            if (userMap.get(sessionEach)<userMap.get(session)){
                num++;
            }
        }
        return num;
    }

    @OnError
    public synchronized void onError(Session session, Throwable error) {
        logger.info("异常"+error.getLocalizedMessage());
    }

}
